﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

/*
 * You might ask: "Why don't any of the .NET COM interfaces inherit from one another,
 * even though they clearly do so in the C/C++ header files?"
 * The answer is that the marshaler ignores the inheritance and flattens the interfaces;
 * you have to specify all functions as they would appear in the v-table,
 * excluding IUnknown or IDispatch which the marshaller adds on its own depending 
 * on the [InterfaceType()] attribute. It sucks and you lose polymorphism but fortunately
 * inheritance appears rarely enough for this to hurt productivity dramatically.
 * 
 * "All exported interfaces extend directly from either IUnknown or IDispatch,
 * regardless of their inheritance hierarchy in managed code."
 * http://www.dotnet247.com/247reference/a.aspx?u=http://tinyurl.com/36c5l
 */
namespace JasLib.Interop.Win32
{
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IAdviseSink)]
    public interface IAdviseSink //: IUnknown
    {
        // TODO:
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IBindCtx)]
    public interface IBindCtx //: IUnknown
    {
        // TODO:
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), GuidAttribute(Constants.InterfaceGuidStrings.IContextMenu)]
    public interface IContextMenu //: IUnknown
    {
        [PreserveSig]
        HRESULT QueryContextMenu(HMENU hMenu, uint indexMenu, uint idCmdFirst, uint idCmdLast, uint uFlags);
        [PreserveSig]
        HRESULT InvokeCommand(ref CMINVOKECOMMANDINFOEX pici);

        /// <summary>
        /// </summary>
        /// <param name="idcmd"></param>
        /// <param name="uflags"></param>
        /// <param name="reserved"></param>
        /// <param name="commandstring"></param>
        /// <param name="cch"></param>
        /// <returns></returns>
        [PreserveSig]
        HRESULT GetCommandString(
            UINT_PTR idcmd,
            GetCommandStringCode uflags,
            ref uint reserved,
            INT_PTR commandstring,
            int cch);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IDispatch)]
    public interface IDispatch
    {
        [PreserveSig]
        HRESULT GetTypeInfoCount([Out] out uint pctinfo);
        [PreserveSig]
        HRESULT GetTypeInfo( 
            [In] uint iTInfo,
            [In] LCID lcid,
            [Out, MarshalAs(UnmanagedType.Interface)] out ITypeInfo ppTInfo);
        /// <param name="rgszNames">Array of string pointers.</param>
        [PreserveSig]
        HRESULT GetIDsOfNames( 
            [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] UINT_PTR[] rgszNames,
            [In] uint cNames,
            [In] LCID lcid,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] DISPID[] rgDispId);
        [PreserveSig]
        HRESULT Invoke( 
            [In] DISPID dispIdMember,
            [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
            [In] LCID lcid,
            [In] ushort wFlags,
            [In, Out] ref DISPPARAMS pDispParams,
            [Out] out VARIANT pVarResult,
            [Out] out EXCEPINFO pExcepInfo,
            [Out] out uint puArgErr);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IDownloadManager)]
    public interface IDownloadManager //: IUnknown
    {
        HRESULT Download(
            IMoniker pmk,
            IBindCtx pbc,
            uint dwBindVerb,
            BINDF grfBINDF,
            ref BINDINFO pBindInfo,
            [MarshalAs(UnmanagedType.LPWStr)] string pszHeaders,
            [MarshalAs(UnmanagedType.LPWStr)] string pszRedir,
            uint uiCP);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IDataObject)]
    public unsafe interface IDataObject
    {
        [PreserveSig]
        HRESULT GetData(ref FORMATETC pformatetcIn, ref STGMEDIUM pmedium);
        [PreserveSig]
        HRESULT GetDataHere(ref FORMATETC pformatetc, ref STGMEDIUM pmedium);
        [PreserveSig]
        HRESULT QueryGetData(ref FORMATETC pformatetc);
        [PreserveSig]
        HRESULT GetCanonicalFormatEtc(ref FORMATETC pformatectIn, ref FORMATETC pformatectOut);
        [PreserveSig]
        HRESULT SetData(ref FORMATETC pformatetc, ref STGMEDIUM pmedium, bool fRelease);
        [PreserveSig]
        HRESULT EnumFormatEtc(uint dwDirection, out IEnumFORMATETC ppenumFormatEtc);
        [PreserveSig]
        HRESULT DAdvise(ref FORMATETC pformatetc, ADVF advf, IAdviseSink pAdvSink, out uint dwConnection);
        [PreserveSig]
        HRESULT DUnadvise(uint dwConnection);
        [PreserveSig]
        HRESULT EnumDAdvise(out IEnumSTATDATA ppenumAdvise);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IDropTarget)]
    public interface IDropTarget //: IUnknown
    {
        [PreserveSig]
        HRESULT DragEnter(IDataObject pDataObj, uint grfKeyState, POINTL pt, out uint pdwEffect);
        [PreserveSig]
        HRESULT DragOver(uint grfKeyState, POINTL pt, out uint pdwEffect);
        [PreserveSig]
        HRESULT DragLeave();
        [PreserveSig]
        HRESULT Drop(IDataObject pDataObj, uint grfKeyState, POINTL pt, out uint pdwEffect);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IEnumFORMATETC)]
    public interface IEnumFORMATETC //: IUnknown
    {
        // TODO:
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IEnumIDList)]
    public interface IEnumIDList //: IUnknown
    {
        /// <param name="rgelt">The address of a pointer to an array of ITEMIDLIST pointers that receive the item identifiers.
        /// The implementation must allocate these item identifiers using CoTaskMemAlloc.
        /// The calling application is responsible for freeing the item identifiers using CoTaskMemFree.
        /// The ITEMIDLIST structures returned in the array are relative to the IShellFolder being enumerated.</param>
        [PreserveSig]
        HRESULT Next(
            [In] uint celt,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] UINT_PTR[] rgelt,
            [Out] out uint pceltFetched);
        [PreserveSig]
        HRESULT Skip(uint celt);
        [PreserveSig]
        HRESULT Reset();
        [PreserveSig]
        HRESULT Clone(out IEnumIDList ppenum);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IEnumShellItems)]
    public interface IEnumShellItems //: IUnknown
    {
        [PreserveSig]
        HRESULT Next(uint celt, out IShellItem rgelt, out uint pceltFetched);
        [PreserveSig]
        HRESULT Skip(uint celt);
        [PreserveSig]
        HRESULT Reset();
        [PreserveSig]
        HRESULT Clone(out IEnumShellItems ppenum);
    }


    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IEnumSTATDATA)]
    public interface IEnumSTATDATA
    {
        // TODO:
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IFileDialog)]
    public interface IFileDialog //: IModalWindow
    {
        #region Copied from IModalWindow
        [PreserveSig]
        HRESULT Show(HWND hwndOwner);
        #endregion

        [PreserveSig]
        HRESULT SetFileTypes(uint cFileTypes, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] COMDLG_FILTERSPEC[] rgFilterSpec);
        [PreserveSig]
        HRESULT SetFileTypeIndex(uint iFileType);
        [PreserveSig]
        HRESULT GetFileTypeIndex(out uint piFileType);
        [PreserveSig]
        HRESULT Advise(IFileDialogEvents pfde, out uint pdwCookie);
        [PreserveSig]
        HRESULT Unadvise(uint dwCookie);
        [PreserveSig]
        HRESULT SetOptions(FILEOPENDIALOGOPTIONS fos);
        [PreserveSig]
        HRESULT GetOptions(out FILEOPENDIALOGOPTIONS pfos);
        [PreserveSig]
        HRESULT SetDefaultFolder(IShellItem psi);
        [PreserveSig]
        HRESULT SetFolder(IShellItem psi);
        [PreserveSig]
        HRESULT GetFolder(out IShellItem ppsi);
        [PreserveSig]
        HRESULT GetCurrentSelection(out IShellItem ppsi);
        [PreserveSig]
        HRESULT SetFileName([In, MarshalAs(UnmanagedType.LPWStr)] string pszName);
        [PreserveSig]
        HRESULT GetFileName([Out, MarshalAs(UnmanagedType.LPWStr)] out string pszName);
        [PreserveSig]
        HRESULT SetTitle([In, MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
        [PreserveSig]
        HRESULT SetOkButtonLabel([In, MarshalAs(UnmanagedType.LPWStr)] string pszText);
        [PreserveSig]
        HRESULT SetFileNameLabel([In, MarshalAs(UnmanagedType.LPWStr)] string pszLabel);
        [PreserveSig]
        HRESULT GetResult(out IShellItem ppsi);
        [PreserveSig]
        HRESULT AddPlace(IShellItem psi, FDAP fdap);
        [PreserveSig]
        HRESULT SetDefaultExtension([In, MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension);
        [PreserveSig]
        HRESULT Close(HRESULT hr);
        [PreserveSig]
        HRESULT SetClientGuid([In, MarshalAs(UnmanagedType.LPStruct)] Guid guid);
        [PreserveSig]
        HRESULT ClearClientData();
        [PreserveSig]
        HRESULT SetFilter(IShellItemFilter pFilter);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IFileDialogEvents)]
    public interface IFileDialogEvents //: IUnknown
    {
        [PreserveSig]
        HRESULT OnFileOk(IFileDialog pfd);
        [PreserveSig]
        HRESULT OnFolderChanging(IFileDialog pfd, IShellItem psiFolder);
        [PreserveSig]
        HRESULT OnFolderChange(IFileDialog pfd);
        [PreserveSig]
        HRESULT OnSelectionChange(IFileDialog pfd);
        [PreserveSig]
        HRESULT OnShareViolation(IFileDialog pfd, IShellItem psi, out FDE_SHAREVIOLATION_RESPONSE pResponse);
        [PreserveSig]
        HRESULT OnTypeChange(IFileDialog pfd);
        [PreserveSig]
        HRESULT OnOverwrite(IFileDialog pfd, IShellItem psi, out FDE_OVERWRITE_RESPONSE pResponse);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IFileOperation)]
    public interface IFileOperation
    {
        [PreserveSig]
        HRESULT Advise([In] IFileOperationProgressSink pfops, out uint pdwCookie);
        [PreserveSig]
        HRESULT Unadvise(uint dwCookie);
        /// <param name="dwOperationFlags">This contains a value from the FILEOP_FLAGS enum, which is typed as a WORD in the header file.</param>
        [PreserveSig]
        HRESULT SetOperationFlags(uint dwOperationFlags);
        [PreserveSig]
        HRESULT SetProgressMessage([In, MarshalAs(UnmanagedType.LPWStr)] string pszMessage);
        [PreserveSig]
        HRESULT SetProgressDialog(IOperationsProgressDialog popd);
        [PreserveSig]
        HRESULT SetProperties(IPropertyChangeArray pproparray);
        [PreserveSig]
        HRESULT SetOwnerWindow([In] HWND hwndOwner);
        [PreserveSig]
        HRESULT ApplyPropertiesToItem(IShellItem psiItem);
        [PreserveSig]
        HRESULT ApplyPropertiesToItems([In] IUnknown punkItem);
        [PreserveSig]
        HRESULT RenameItem(
            [In] IShellItem psiItem,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszNewName,
            IFileOperationProgressSink pfopsItem);
        [PreserveSig]
        HRESULT RenameItems(
            [In] IUnknown punkItems,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszNewName);
        [PreserveSig]
        HRESULT MoveItem(
            [In] IShellItem psiItem,
            [In] IShellItem psiDestinationFolder,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszNewName,
            [In] IFileOperationProgressSink pfopsItem);
        [PreserveSig]
        HRESULT MoveItems(
            [In] IUnknown punkItems,
            [In] IShellItem psiDestinationFolder);
        [PreserveSig]
        HRESULT CopyItem(
            [In] IShellItem psiItem,
            [In] IShellItem psiDestinationFolder,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszCopyName,
            IFileOperationProgressSink pfopsItem);
        [PreserveSig]
        HRESULT CopyItems(
            [In] IUnknown punkItems,
            [In] IShellItem psiDestinationFolder);
        [PreserveSig]
        HRESULT DeleteItem(
            IShellItem psiItem,
            IFileOperationProgressSink pfopsItem);
        [PreserveSig]
        HRESULT DeleteItems(IUnknown punkItems);
        [PreserveSig]
        HRESULT NewItem(
            IShellItem psiDestinationFolder,
            FileFlagsAndAttributes dwFileAttributes,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszName,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszTemplateName,
            IFileOperationProgressSink pfopsItem);
        [PreserveSig]
        HRESULT PerformOperations();
        [PreserveSig]
        HRESULT GetAnyOperationsAborted(out bool pfAnyOperationsAborted);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IFileOperationProgressSink)]
    public interface IFileOperationProgressSink
    {
        [PreserveSig]
        HRESULT StartOperations();
        [PreserveSig]
        HRESULT FinishOperations(HRESULT hrResult);
        [PreserveSig]
        HRESULT PreRenameItem(
            TRANSFER_SOURCE_FLAGS dwFlags,
            IShellItem psiItem,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszNewName);
        [PreserveSig]
        HRESULT PostRenameItem(
            TRANSFER_SOURCE_FLAGS dwFlags,
            IShellItem psiItem,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszNewName,
            HRESULT hrRename,
            IShellItem psiNewlyCreated);
        [PreserveSig]
        HRESULT PreMoveItem(
            TRANSFER_SOURCE_FLAGS dwFlags,
            IShellItem psiItem,
            IShellItem psiDestinationFolder,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszNewName);
        [PreserveSig]
        HRESULT PostMoveItem(
            TRANSFER_SOURCE_FLAGS dwFlags,
            IShellItem psiItem,
            IShellItem psiDestinationFolder,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszNewName,
            HRESULT hrMove,
            IShellItem psiNewlyCreated);
        [PreserveSig]
        HRESULT PreCopyItem(
            TRANSFER_SOURCE_FLAGS dwFlags,
            IShellItem psiItem,
            IShellItem psiDestinationFolder,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszNewName);
        [PreserveSig]
        HRESULT PostCopyItem(
            TRANSFER_SOURCE_FLAGS dwFlags,
            IShellItem psiItem,
            IShellItem psiDestinationFolder,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszNewName,
            HRESULT hrCopy,
            IShellItem psiNewlyCreated);
        [PreserveSig]
        HRESULT PreDeleteItem(
            TRANSFER_SOURCE_FLAGS dwFlags,
            IShellItem psiItem);
        [PreserveSig]
        HRESULT PostDeleteItem(
            TRANSFER_SOURCE_FLAGS dwFlags,
            IShellItem psiItem,
            HRESULT hrDelete,
            IShellItem psiNewlyCreated);
        [PreserveSig]
        HRESULT PreNewItem(
            TRANSFER_SOURCE_FLAGS dwFlags,
            IShellItem psiDestinationFolder,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszNewName);
        [PreserveSig]
        HRESULT PostNewItem(
            TRANSFER_SOURCE_FLAGS dwFlags,
            IShellItem psiDestinationFolder,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszNewName,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszTemplateName,
            FileFlagsAndAttributes dwFileAttributes,
            HRESULT hrNew,
            IShellItem psiNewItem);
        [PreserveSig]
        HRESULT UpdateProgress(
            uint iWorkTotal,
            uint iWorkSoFar);
        [PreserveSig]
        HRESULT ResetTimer();
        [PreserveSig]
        HRESULT PauseTimer();
        [PreserveSig]
        HRESULT ResumeTimer();
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IFileSaveDialog)]
    public interface IFileSaveDialog //: IFileDialog
    {
        #region Copied from IModalWindow
        [PreserveSig]
        HRESULT Show(HWND hwndOwner);
        #endregion

        #region Copied from IFileDialog
        [PreserveSig]
        HRESULT SetFileTypes(
            uint cFileTypes,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] COMDLG_FILTERSPEC[] rgFilterSpec);
        [PreserveSig]
        HRESULT SetFileTypeIndex(uint iFileType);
        [PreserveSig]
        HRESULT GetFileTypeIndex(out uint piFileType);
        [PreserveSig]
        HRESULT Advise(IFileDialogEvents pfde, out uint pdwCookie);
        [PreserveSig]
        HRESULT Unadvise(uint dwCookie);
        [PreserveSig]
        HRESULT SetOptions(FILEOPENDIALOGOPTIONS fos);
        [PreserveSig]
        HRESULT GetOptions(out FILEOPENDIALOGOPTIONS pfos);
        [PreserveSig]
        HRESULT SetDefaultFolder(IShellItem psi);
        [PreserveSig]
        HRESULT SetFolder(IShellItem psi);
        [PreserveSig]
        HRESULT GetFolder(out IShellItem ppsi);
        [PreserveSig]
        HRESULT GetCurrentSelection(out IShellItem ppsi);
        [PreserveSig]
        HRESULT SetFileName([In, MarshalAs(UnmanagedType.LPWStr)] string pszName);
        [PreserveSig]
        HRESULT GetFileName([Out, MarshalAs(UnmanagedType.LPWStr)] out string pszName);
        [PreserveSig]
        HRESULT SetTitle([In, MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
        [PreserveSig]
        HRESULT SetOkButtonLabel([In, MarshalAs(UnmanagedType.LPWStr)] string pszText);
        [PreserveSig]
        HRESULT SetFileNameLabel([In, MarshalAs(UnmanagedType.LPWStr)] string pszLabel);
        [PreserveSig]
        HRESULT GetResult(out IShellItem ppsi);
        [PreserveSig]
        HRESULT AddPlace(IShellItem psi, FDAP fdap);
        [PreserveSig]
        HRESULT SetDefaultExtension([In, MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension);
        [PreserveSig]
        HRESULT Close(HRESULT hr);
        [PreserveSig]
        HRESULT SetClientGuid([In, MarshalAs(UnmanagedType.LPStruct)] Guid guid);
        [PreserveSig]
        HRESULT ClearClientData();
        [PreserveSig]
        HRESULT SetFilter(IShellItemFilter pFilter);
        #endregion

        [PreserveSig]
        HRESULT SetSaveAsItem(IShellItem psi);
        [PreserveSig]
        HRESULT SetProperties(IPropertyStore pStore);
        [PreserveSig]
        HRESULT SetCollectedProperties(IPropertyDescriptionList pList, [MarshalAs(UnmanagedType.Bool)] bool fAppendDefault);
        [PreserveSig]
        HRESULT GetProperties(out IPropertyStore ppStore);
        [PreserveSig]
        HRESULT ApplyProperties(IShellItem psi, IPropertyStore pStore, HWND hwnd, IFileOperationProgressSink pSink);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IInternetSecurityManager)]
    public interface IInternetSecurityManager
    {
        // TODO:
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IInternetSecurityManagerEx2)]
    public interface IInternetSecurityManagerEx2
    {
        // TODO:
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IMalloc)]
    public interface IMalloc //: IUnknown
    {
        [PreserveSig]
        UINT_PTR Alloc([In] UINT_PTR cb);
        [PreserveSig]
        UINT_PTR Realloc(UINT_PTR pv, UINT_PTR cb);
        [PreserveSig]
        void Free(UINT_PTR pv);
        [PreserveSig]
        UINT_PTR GetSize(UINT_PTR pv);
        [PreserveSig]
        int DidAlloc(UINT_PTR pv);
        [PreserveSig]
        void HeapMinimize();
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IModalWindow)]
    public interface IModalWindow //: IUnknown
    {
        [PreserveSig]
        HRESULT Show(HWND hwndOwner);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IMoniker)]
    public interface IMoniker
    {
        // TODO:
    }

    public interface IOperationsProgressDialog
    {
        // TODO:
    }

    public interface IPropertyChangeArray
    {
        // TODO:
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IPropertyDescriptionList)]
    public interface IPropertyDescriptionList
    {
        // TODO:
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IPropertyStore)]
    public interface IPropertyStore
    {
        // TODO:
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IRecordInfo)]
    public interface IRecordInfo
    {
        // TODO:
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IShellFolder)]
    public interface IShellFolder //: IUnknown
    {
        /// <summary>
        /// Translates a file object's or folder's display name into an item
        /// identifier list.
        /// Return value: error code, if any
        /// </summary>
        /// <param name="hwnd">Optional window handle</param>
        /// <param name="pbc">Optional bind context that controls the parsing operation. This parameter is normally set to NULL.</param>
        /// <param name="pszDisplayName">Null-terminated UNICODE string with the display name.</param>
        /// <param name="pchEaten">Pointer to a ULONG value that receives the number of characters of the display name that was parsed.</param>
        /// <param name="ppidl">Pointer to an ITEMIDLIST pointer that receives the item identifier list for the object.</param>
        /// <param name="pdwAttributes">Optional parameter that can be used to query for file attributes. this can be values from the SFGAO enum</param>
        /// <returns></returns>
        [PreserveSig]
        HRESULT ParseDisplayName(
            HWND hwnd,
            IBindCtx pbc,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName,
            out uint pchEaten,
            out LPITEMIDLIST ppidl,
            ref SFGAOF pdwAttributes);

        /// <summary>
        /// Allows a client to determine the contents of a folder by creating
        /// an item identifier enumeration object and returning its
        /// IEnumIDList interface.
        /// </summary>
        /// <param name="hwnd">If user input is required to perform the
        /// enumeration, this window handle
        /// should be used by the enumeration object as
        /// the parent window to take
        /// user input.</param>
        /// <param name="grfFlags">Flags indicating which items to include in the
        /// enumeration. For a list
        /// of possible values, see the SHCONTF enum.</param>
        /// <param name="ppenumIDList">Address that receives a pointer to the
        /// IEnumIDList interface of the
        /// enumeration object created by this method.</param>
        /// <returns></returns>
        [PreserveSig]
        HRESULT EnumObjects(
            HWND hwnd,
            SHCONTF grfFlags,
            out IEnumIDList ppenumIDList);

        /// <summary>
        // Retrieves an IShellFolder object for a subfolder.
        /// </summary>
        /// <param name="pidl">Address of an ITEMIDLIST structure (PIDL)
        // that identifies the subfolder.</param>
        /// <param name="pbc">Optional address of an IBindCtx interface on
        // a bind context object to be
        // used during this operation.</param>
        /// <param name="riid">Identifier of the interface to return.</param>
        /// <param name="ppv">Address that receives the interface pointer.</param>
        [PreserveSig]
        HRESULT BindToObject(
            LPITEMIDLIST pidl,
            IBindCtx pbc,
            [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
            [MarshalAs(UnmanagedType.Interface)] out object ppv);

        /// <summary>
        /// Requests a pointer to an object's storage interface.
        /// </summary>
        /// <param name="pidl">Address of an ITEMIDLIST structure that
        // identifies the subfolder relative
        // to its parent folder.</param>
        /// <param name="pbc">Optional address of an IBindCtx interface on a
        // bind context object to be
        // used during this operation.</param>
        /// <param name="riid">Interface identifier (IID) of the requested storage interface.</param>
        /// <param name="ppv">Address that receives the interface pointer specified by riid.</param>
        /// <returns></returns>
        [PreserveSig]
        HRESULT BindToStorage(
            LPITEMIDLIST pidl,
            IBindCtx pbc,
            [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
            [MarshalAs(UnmanagedType.Interface)] out object ppv);

        /// <summary>
        /// Determines the relative order of two file objects or folders, given
        /// their item identifier lists. Return value: If this method is
        /// successful, the CODE field of the HRESULT contains one of the
        /// following values (the code can be retrived using the helper function
        /// GetHResultCode):
        /// Negative A negative return value indicates that the first item should precede the second (pidl1 &lt; pidl2).
        /// Positive A positive return value indicates that the first item should follow the second (pidl1 &gt; pidl2).
        /// Zero A return value of zero indicates that the two items are the same (pidl1 = pidl2).
        /// </summary>
        /// <param name="lParam">Value that specifies how the comparison
        /// should be performed. The lower Sixteen bits of lParam define the sorting rule.
        /// The upper sixteen bits of lParam are used for flags that modify the
        /// sorting rule. values can be from the SHCIDS enum</param>
        /// <param name="pidl1">Pointer to the first item's ITEMIDLIST structure.</param>
        /// <param name="pidl2">Pointer to the second item's ITEMIDLIST structure.</param>
        /// <returns></returns>
        [PreserveSig]
        HRESULT CompareIDs(INT_PTR lParam, [In] LPITEMIDLIST pidl1, [In] LPITEMIDLIST pidl2);

        /// <summary>
        // Requests an object that can be used to obtain information from or interact
        // with a folder object.
        /// </summary>
        /// <param name="hwndOwner">Handle to the owner window.</param>
        /// <param name="riid">Identifier of the requested interface.</param>
        /// <param name="ppv">Address of a pointer to the requested interface.</param>
        [PreserveSig]
        HRESULT CreateViewObject(
            HWND hwndOwner,
            [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
            [MarshalAs(UnmanagedType.Interface)] out object ppv);

        /// <summary>
        /// Retrieves the attributes of one or more file objects or subfolders.
        /// Return value: error code, if any
        /// </summary>
        /// <param name="cidl">Number of file objects from which to retrieve attributes.</param>
        /// <param name="apidl">Address of an array of pointers to ITEMIDLIST
        /// structures, each of which
        /// uniquely identifies a file object relative to
        /// the parent folder.</param>
        /// <param name="rgfInOut">Address of a single ULONG value that, on entry,
        /// contains the attributes that the caller is
        /// requesting. On exit, this value contains the
        /// requested attributes that are common to all
        /// of the specified objects. this value can
        /// be from the SFGAO enum</param>
        /// <returns></returns>
        [PreserveSig]
        HRESULT GetAttributesOf(
            uint cidl,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] UINT_PTR[] apidl,
            ref SFGAOF rgfInOut);

        /// <summary>
        /// Retrieves an OLE interface that can be used to carry out actions on the
        /// specified file objects or folders. Return value: error code, if any
        /// </summary>
        /// <param name="hwndOwner">Handle to the owner window that the client
        /// should specify if it displays
        /// a dialog box or message box.</param>
        /// <param name="cidl">Number of file objects or subfolders specified
        /// in the apidl parameter.</param>
        /// <param name="apidl">Address of an array of pointers to ITEMIDLIST
        // structures, each of which
        // uniquely identifies a file object or subfolder
        // relative to the parent folder.</param>
        /// <param name="riid">Identifier of the COM interface object to return.</param>
        /// <param name="rgfReserved">Reserved.</param>
        /// <param name="ppv">Pointer to the requested interface.</param>
        /// <returns></returns>
        [PreserveSig]
        HRESULT GetUIObjectOf(
            HWND hwndOwner,
            int cidl,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] INT_PTR[] apidl,
            [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
            INT_PTR rgfReserved,
            [MarshalAs(UnmanagedType.Interface)] out object ppv);

        /// <summary>
        /// Retrieves the display name for the specified file object or subfolder.
        /// </summary>
        /// <param name="pidl">Address of an ITEMIDLIST structure (PIDL) that uniquely identifies the file object or subfolder relative to the parent folder.</param>
        /// <param name="uFlags">Flags used to request the type of display name to return. For a list of possible values.</param>
        /// <param name="pName">Address of a STRRET structure in which to return the display name.</param>
        /// <returns></returns>
        [PreserveSig]
        HRESULT GetDisplayNameOf([In] LPITEMIDLIST pidl, SHGDNF uFlags, [Out] out STRRET pName);

        /// <summary>
        /// Sets the display name of a file object or subfolder, changing the item
        /// identifier in the process.
        /// </summary>
        /// <param name="hwnd">Handle to the owner window of any dialog or
        /// message boxes that the client displays.</param>
        /// <param name="pidl">Pointer to an ITEMIDLIST structure that uniquely
        /// identifies the file object
        /// or subfolder relative to the parent folder.</param>
        /// <param name="pszName">Pointer to a null-terminated string that
        /// specifies the new display name.</param>
        /// <param name="uFlags">Flags indicating the type of name specified by
        /// the lpszName parameter. For a list of possible
        /// values, see the description of the SHGNO enum.</param>
        /// <param name="ppidlOut">Address of a pointer to an ITEMIDLIST structure
        /// which receives the new ITEMIDLIST.</param>
        /// <returns></returns>
        [PreserveSig]
        HRESULT SetNameOf(
            [In] HWND hwnd,
            [In] LPITEMIDLIST pidl,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszName,
            [In] SHGDNF uFlags,
            [Out] out LPITEMIDLIST ppidlOut);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <remarks>
    /// It is the responsibility of the caller to free the string pointed to by ppszName when it is no longer needed.
    /// Call CoTaskMemFree on *ppszName to free the memory, or call InterfaceExtensions.GetDisplayName(this IShellItem) to handle all details.
    /// </remarks>
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IShellItem)]
    public interface IShellItem //: IUnknown
    {
        [PreserveSig]
        HRESULT BindToHandler([In] IBindCtx pbc, [In, MarshalAs(UnmanagedType.LPStruct)] Guid bhid, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppv);
        [PreserveSig]
        HRESULT GetParent(out IShellItem ppsi);
        [PreserveSig]
        HRESULT GetDisplayName(SIGDN sigdnName, out UINT_PTR ppszName);
        [PreserveSig]
        HRESULT GetAttributes([In] SFGAOF sfgaoMask, [Out] out SFGAOF psfgaoAttribs);
        [PreserveSig]
        HRESULT Compare([In] IShellItem psi, SICHINTF hint, out int piOrder);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IShellItem2)]
    public interface IShellItem2 //: IShellItem
    {
        #region Copied from IShellItem
        [PreserveSig]
        HRESULT BindToHandler([In] IBindCtx pbc, [In, MarshalAs(UnmanagedType.LPStruct)] Guid bhid, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppv);
        [PreserveSig]
        HRESULT GetParent(out IShellItem ppsi);
        [PreserveSig]
        HRESULT GetDisplayName(SIGDN sigdnName, out UINT_PTR ppszName);
        [PreserveSig]
        HRESULT GetAttributes([In] SFGAOF sfgaoMask, [Out] out SFGAOF psfgaoAttribs);
        [PreserveSig]
        HRESULT Compare([In] IShellItem psi, SICHINTF hint, out int piOrder);
        #endregion

        [PreserveSig]
        HRESULT GetPropertyStore(GETPROPERTYSTOREFLAGS flags, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppv);
        [PreserveSig]
        HRESULT GetPropertyStoreWithCreateObject(GETPROPERTYSTOREFLAGS flags, IUnknown punkCreateObject, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppv);
        [PreserveSig]
        HRESULT GetPropertyStoreForKeys([In] ref PROPERTYKEY rgKeys, uint cKeys, GETPROPERTYSTOREFLAGS flags, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppv);
        [PreserveSig]
        HRESULT GetPropertyDescriptionList([In] ref PROPERTYKEY keyType, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppv);
        [PreserveSig]
        HRESULT Update([In] IBindCtx pbc);
        [PreserveSig]
        HRESULT GetProperty([In] ref PROPERTYKEY key, [Out] out PROPVARIANT ppropvar);
        [PreserveSig]
        HRESULT GetCLSID([In] ref PROPERTYKEY key, out Guid pclsid);
        [PreserveSig]
        HRESULT GetFileTime([In] ref PROPERTYKEY key, out FILETIME pft);
        [PreserveSig]
        HRESULT GetInt32([In] ref PROPERTYKEY key, out int pi);
        [PreserveSig]
        HRESULT GetString([In] ref PROPERTYKEY key, [MarshalAs(UnmanagedType.LPWStr)] out string ppsz);
        [PreserveSig]
        HRESULT GetUInt32([In] ref PROPERTYKEY key, out uint pui);
        [PreserveSig]
        HRESULT GetUInt64([In] ref PROPERTYKEY key, out ulong pull);
        [PreserveSig]
        HRESULT GetBool([In] ref PROPERTYKEY key, out bool pf);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IShellItemArray)]
    public interface IShellItemArray //: IUnknown
    {
        [PreserveSig]
        HRESULT BindToHandler([In] IBindCtx pbc, [In, MarshalAs(UnmanagedType.LPStruct)] Guid bhid, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppvOut);
        [PreserveSig]
        HRESULT GetPropertyStore(GETPROPERTYSTOREFLAGS flags, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppv);
        [PreserveSig]
        HRESULT GetPropertyDescriptionList([In] ref PROPERTYKEY keyType, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppv);
        [PreserveSig]
        HRESULT GetAttributes(SIATTRIBFLAGS AttribFlags, SFGAOF sfgaoMask, out SFGAOF psfgaoAttribs);
        [PreserveSig]
        HRESULT GetCount(out uint pdwNumItems);
        [PreserveSig]
        HRESULT GetItemAt(uint dwIndex, out IShellItem ppsi);
        [PreserveSig]
        HRESULT EnumItems(out IEnumShellItems ppenumShellItems);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IShellItemFilter)]
    public interface IShellItemFilter //: IUnknown
    {
        [PreserveSig]
        HRESULT IncludeItem(IShellItem psi);
        [PreserveSig]
        HRESULT GetEnumFlagsForItem(IShellItem psi, out SHCONTF pgrfFlags);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IShellLinkW)]
    public interface IShellLinkW
    {
        [PreserveSig]
        HRESULT GetPath(
            [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
            int cch,
            out WIN32_FIND_DATA pfd,
            [In] SLGP_FLAGS fFlags);
        [PreserveSig]
        HRESULT GetIDList(ref LPITEMIDLIST ppidl);
        [PreserveSig]
        HRESULT SetIDList(LPITEMIDLIST pidl);
        [PreserveSig]
        HRESULT GetDescription(
            [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
            int cch);
        [PreserveSig]
        HRESULT SetDescription([In, MarshalAs(UnmanagedType.LPWStr)] string pszName);
        [PreserveSig]
        HRESULT GetWorkingDirectory(
            [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
            int cch);
        [PreserveSig]
        HRESULT SetWorkingDirectory([In, MarshalAs(UnmanagedType.LPWStr)] string pszDir);
        [PreserveSig]
        HRESULT GetArguments(
            [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
            int cch);
        [PreserveSig]
        HRESULT SetArguments([In, MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
        [PreserveSig]
        HRESULT GetHotkey(ref ushort pwHotkey);
        [PreserveSig]
        HRESULT SetHotkey(ushort wHotkey);
        [PreserveSig]
        HRESULT GetShowCmd(ref int piShowCmd);
        [PreserveSig]
        HRESULT SetShowCmd(int iShowCmd);
        [PreserveSig]
        HRESULT GetIconLocation(
            [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
            int cch,
            out int piIcon);
        [PreserveSig]
        HRESULT SetIconLocation(
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszIconPath,
            int iIcon);
        [PreserveSig]
        HRESULT SetRelativePath(
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
            [In] uint dwReserved);
        [PreserveSig]
        HRESULT Resolve(HWND hwnd, [In] SLR_FLAGS fFlags);
        [PreserveSig]
        HRESULT SetPath([In, MarshalAs(UnmanagedType.LPWStr)] string pszFile);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.ITypeInfo)]
    public interface ITypeInfo
    {
        /// TODO:
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IUnknown)]
    public interface IUnknown
    {
        [PreserveSig]
        HRESULT QueryInterface([In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppvObject);
        [PreserveSig]
        uint AddRef();
        [PreserveSig]
        uint Release();
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IUri)]
    public interface IUri
    {
        [PreserveSig]
        HRESULT GetPropertyBSTR(Uri_PROPERTY uriProp, [Out, MarshalAs(UnmanagedType.BStr)] string pbstrProperty, uint dwFlags);
        [PreserveSig]
        HRESULT GetPropertyLength(Uri_PROPERTY uriProp, out uint pcchProperty, uint dwFlags);
        [PreserveSig]
        HRESULT GetPropertyDWORD(Uri_PROPERTY uriProp, out uint pdwProperty, uint dwFlags);
        [PreserveSig]
        HRESULT HasProperty(Uri_PROPERTY uriProp, out bool pfHasProperty);
        [PreserveSig]
        HRESULT GetAbsoluteUri([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrAbsoluteUri);
        [PreserveSig]
        HRESULT GetAuthority([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrAuthority);
        [PreserveSig]
        HRESULT GetDisplayUri([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrDisplayString);
        [PreserveSig]
        HRESULT GetDomain([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrDomain);
        [PreserveSig]
        HRESULT GetExtension([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrExtension);
        [PreserveSig]
        HRESULT GetFragment([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrFragment);
        [PreserveSig]
        HRESULT GetHost([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrHost);
        [PreserveSig]
        HRESULT GetPassword([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrPassword);
        [PreserveSig]
        HRESULT GetPath([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrPath);
        [PreserveSig]
        HRESULT GetPathAndQuery([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrPathAndQuery);
        [PreserveSig]
        HRESULT GetQuery([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrQuery);
        [PreserveSig]
        HRESULT GetRawUri([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrRawUri);
        [PreserveSig]
        HRESULT GetSchemeName([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrSchemeName);
        [PreserveSig]
        HRESULT GetUserInfo([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrUserInfo);
        [PreserveSig]
        HRESULT GetUserName([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrUserName);
        [PreserveSig]
        HRESULT GetHostType(out uint pdwHostType);
        [PreserveSig]
        HRESULT GetPort(out uint pdwPort);
        [PreserveSig]
        HRESULT GetScheme(out uint pdwScheme);
        [PreserveSig]
        HRESULT GetZone(out uint pdwZone);
        [PreserveSig]
        HRESULT GetProperties(out uint pdwFlags);
        [PreserveSig]
        HRESULT IsEqual(IUri pUri, out bool pfEqual);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IWbemClassObject)]
    public interface IWbemClassObject
    {
        [PreserveSig]
        HRESULT GetQualifierSet( 
            [Out, MarshalAs(UnmanagedType.Interface)] out IWbemQualifierSet ppQualSet);
        [PreserveSig] HRESULT Get( 
            [In, MarshalAs(UnmanagedType.LPWStr)] string wszName,
            [In] int lFlags,
            [Out] out VARIANT pVal,
            [Out] out CIMTYPE pType,
            [Out] out int plFlavor);
        [PreserveSig] HRESULT Put(
            [In, MarshalAs(UnmanagedType.LPWStr)] string wszName,
            [In] int lFlags,
            [In] ref VARIANT pVal,
            [In] CIMTYPE Type);
        [PreserveSig]
        HRESULT Delete(
            [In, MarshalAs(UnmanagedType.LPWStr)] string wszName);
        [PreserveSig]
        HRESULT GetNames(
            [In, MarshalAs(UnmanagedType.LPWStr)] string wszQualifierName,
            [In] int lFlags,
            [In] ref VARIANT pQualifierVal,
            [Out] out LPSAFEARRAY pNames);
        [PreserveSig] HRESULT BeginEnumeration( 
            [In] int lEnumFlags);
        [PreserveSig] HRESULT Next(
            [In] int lFlags,
            //* [unique][in][out] */ BSTR* strName,
            [Out] out VARIANT pVal,
            [Out] out CIMTYPE pType,
            [Out] out int plFlavor);
        [PreserveSig]
        HRESULT EndEnumeration();
        [PreserveSig] HRESULT GetPropertyQualifierSet(
            [In, MarshalAs(UnmanagedType.LPWStr)] string wszProperty,
            [Out, MarshalAs(UnmanagedType.Interface)] out IWbemQualifierSet ppQualSet);
        [PreserveSig] HRESULT Clone(
            [Out, MarshalAs(UnmanagedType.Interface)] out IWbemClassObject ppCopy);
        [PreserveSig] HRESULT GetObjectText(
            [In] int lFlags,
            /* [out]  BSTR* */ string pstrObjectText);
        [PreserveSig]
        HRESULT SpawnDerivedClass(
            [In] int lFlags,
            [Out, MarshalAs(UnmanagedType.Interface)] out IWbemClassObject ppNewClass);
        [PreserveSig]
        HRESULT SpawnInstance(
            [In] int lFlags,
            [Out, MarshalAs(UnmanagedType.Interface)] out IWbemClassObject ppNewInstance);
        [PreserveSig]
        HRESULT CompareTo(
            [In] int lFlags,
            [In, MarshalAs(UnmanagedType.Interface)] IWbemClassObject pCompareTo);
        [PreserveSig]
        HRESULT GetPropertyOrigin( 
            //* [string][in] */ LPCWSTR wszName,
            /* [out]  BSTR* */ string pstrClassName);
        [PreserveSig]
        HRESULT InheritsFrom(
            [In, MarshalAs(UnmanagedType.LPWStr)] string strAncestor);
        [PreserveSig]
        HRESULT GetMethod(
            [In, MarshalAs(UnmanagedType.LPWStr)] string wszName,
            [In] int lFlags,
            [Out, MarshalAs(UnmanagedType.Interface)] out IWbemClassObject ppInSignature,
            [Out, MarshalAs(UnmanagedType.Interface)] out IWbemClassObject ppOutSignature);
        [PreserveSig] HRESULT PutMethod(
            [In, MarshalAs(UnmanagedType.LPWStr)] string wszName,
            [In] int lFlags,
            [In, MarshalAs(UnmanagedType.Interface)] IWbemClassObject pInSignature,
            [In, MarshalAs(UnmanagedType.Interface)] IWbemClassObject pOutSignature);
        [PreserveSig]
        HRESULT DeleteMethod(
            [In, MarshalAs(UnmanagedType.LPWStr)] string wszName);
        [PreserveSig]
        HRESULT BeginMethodEnumeration([In] long lEnumFlags);
        [PreserveSig]
        HRESULT NextMethod( 
            [In] int lFlags,
            //* [unique][in][out] */ BSTR *pstrName,
            [In, MarshalAs(UnmanagedType.Interface)] IWbemClassObject ppInSignature,
            [In, Out, MarshalAs(UnmanagedType.Interface)] ref IWbemClassObject ppOutSignature);
        [PreserveSig]
        HRESULT EndMethodEnumeration();
        [PreserveSig]
        HRESULT GetMethodQualifierSet(
            [In, MarshalAs(UnmanagedType.LPWStr)] string wszMethod,
            [Out, MarshalAs(UnmanagedType.Interface)] out IWbemQualifierSet ppQualSet);
        [PreserveSig]
        HRESULT GetMethodOrigin(
            [In, MarshalAs(UnmanagedType.LPWStr)] string wszMethodName,
            /* [out]  BSTR* */ string pstrClassName);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IWbemContext)]
    public interface IWbemContext
    {
        /// TODO:
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IWbemLocator)]
    public interface IWbemLocator
    {
        [PreserveSig]
        HRESULT ConnectServer(
            [In, MarshalAs(UnmanagedType.BStr)] string strNetworkResource,
            [In, MarshalAs(UnmanagedType.BStr)] string strUser,
            [In, MarshalAs(UnmanagedType.BStr)] string strPassword,
            [In, MarshalAs(UnmanagedType.BStr)] string strLocale,
            [In] int lSecurityFlags,
            [In, MarshalAs(UnmanagedType.BStr)] string strAuthority,
            [In, MarshalAs(UnmanagedType.Interface)] IWbemContext pCtx,
            [Out, MarshalAs(UnmanagedType.Interface)] out IWbemServices ppNamespace);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IWbemQualifierSet)]
    public interface IWbemQualifierSet
    {
        /// TODO:
        /*virtual HRESULT STDMETHODCALLTYPE Get( 
             [string][in]  LPCWSTR wszName,
             [in]  long lFlags,
             [unique][in][out]  VARIANT *pVal,
             [unique][in][out]  long *plFlavor) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE Put( 
             [string][in]  LPCWSTR wszName,
             [in]  VARIANT *pVal,
             [in]  long lFlavor) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE Delete( 
             [string][in]  LPCWSTR wszName) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE GetNames( 
             [in]  long lFlags,
             [out]  SAFEARRAY * *pNames) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE BeginEnumeration( 
             [in]  long lFlags) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE Next( 
             [in]  long lFlags,
             [unique][in][out]  BSTR *pstrName,
             [unique][in][out]  VARIANT *pVal,
             [unique][in][out]  long *plFlavor) = 0;
*/
        [PreserveSig]
        HRESULT EndEnumeration();
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IWbemQuery)]
    public interface IWbemQuery
    {
        [PreserveSig]
        HRESULT Empty();
        [PreserveSig]
        HRESULT SetLanguageFeatures(
            [In] uint uFlags,
            [In] uint uArraySize,
            [In] uint[] puFeatures);
        [PreserveSig]
        HRESULT TestLanguageFeatures(
            [In] uint uFlags,
            [In, Out] ref uint uArraySize,
            [Out] uint[] puFeatures);
        [PreserveSig]
        HRESULT Parse(
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszLang,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszQuery,
            [In] uint uFlags);
        [PreserveSig]
        HRESULT GetAnalysis(
            [In] WMIQ_ANALYSIS_TYPE uAnalysisType,
            [In] uint uFlags,
            [Out] out UINT_PTR pAnalysis);
        [PreserveSig]
        HRESULT FreeMemory(UINT_PTR pMem);
        [PreserveSig]
        HRESULT GetQueryInfo(
            [In] uint uAnalysisType,
            [In] uint uInfoId,
            [In] uint uBufSize,
            [Out] byte[] pDestBuf);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Constants.InterfaceGuidStrings.IWbemServices)]
    public interface IWbemServices
    {
        /// TODO:
    }
}